import axios from 'axios';
import qs from 'qs';
import type { AxiosRequestConfig, AxiosRequestHeaders, AxiosResponse, Canceler, Method } from 'axios';
import type { IRequestOptions, IResponse, RequestContentType } from './interface';

const requestTokenKey: string = 'Authorization';

const request = axios.create({
    baseURL: import.meta.env.VITE_BASE_API,
    withCredentials: true,
    timeout: 30 * 1000,
});

// 请求发起拦截器
request.interceptors.request.use(
    (config: any) => {
        try {
            const data = config.data || {};
            // 可以添加
            config.data = JSON.stringify(data);
        } catch (err) {}
        config.cancelToken = new axios.CancelToken(function executor(cancel: Canceler): void {
            // 处理其他的东西
        });
        return config;
    },
    (error) => {
        return Promise.reject(error);
    }
);

// 响应拦截器
request.interceptors.response.use(
    (response: AxiosResponse<any>) => {
        const { status, data } = response;
        if (status === 200) {
            if (data.result === 0) {
                return data;
            } else if (data.result === 401) {
                //出现特殊标识code后取消后面的请求
                // todo
            } else {
                return data;
            }
        } else {
            return data;
        }
    },
    (error) => {
        return Promise.reject(error);
    }
);

const handleResponse = (
    result: IResponse,
    hideError: boolean,
    returnAllResponse: boolean,
    isShowResponseMessage: boolean
) => {
    if (!hideError) {
        if (result) {
            if (result.message !== 'request-cancel') {
                let message = result.message == 'Network Error' ? '服务器或网络开小差了，请稍后再试~' : result.message;
                if (result.code !== 0) {
                    // todo
                } else {
                    // 配置属性
                    // isShowResponseMessage
                }
            }
        }
    }
    if (returnAllResponse) {
        return result;
    }
    return result?.data ?? null;
};

// 处理请求类型
const rebuildPostData = (params: unknown, contentType: RequestContentType) => {
    let headersConfig: string = '';
    switch (contentType) {
        case 'JSON':
            headersConfig = 'application/json';
            break;
        case 'FORMDATA':
            headersConfig = 'multipart/form-data';
            break;
        case 'WWWFORM':
            headersConfig = 'application/x-www-form-urlencoded';
            params = qs.stringify(params);
            break;
    }

    return {
        headersConfig,
        params,
    };
};

// 是否有loading
const useLoading = (isShowLoading: boolean) => {
    let loadingInstance = null;
    if (isShowLoading) {
        // 显示loading
    }

    // 返回想要的参数
    return {
        loadingInstance,
    };
};

// const useRequestHeaders = (headers: AxiosRequestHeaders, isNoNeedToken: boolean): AxiosRequestHeaders => {
//     if(!isNoNeedToken && getCookie()?.token) {
//         headers[requestTokenKey] = getCookie()?.token as string
//     }
//     return headers
// }

export default {
    /**
     * GET 请求
     * @template T
     * @param {string} url - 请求地址
     * @param {(Record<string | number,unknown | any>)} [params={}] - 请求参数
     * @param {IRequestOptions} [{
     *         hideError = false,
     *         returnAllResponse = false,
     *         isShowLoading = false,
     *         isShowResponseMessage = false
     *     }={}]
     * @return {*}  {Promise<T>}
     */
    httpGet<T = IResponse>(
        url: string,
        params: Record<string | number, unknown | any> = {},
        {
            hideError = false,
            returnAllResponse = false,
            isShowLoading = false,
            isShowResponseMessage = false,
        }: IRequestOptions = {}
    ): Promise<T> {
        const method: Method = 'GET';
        // const headers: AxiosRequestHeaders = {}
        // 这里拿到loading的返回值
        const { loadingInstance } = useLoading(isShowLoading);
        const config: AxiosRequestConfig = {
            url,
            method,
            params,
            // headers: useRequestHeaders(headers,isNoNeedToken),
        };
        if (Object.keys(params).length == 0) {
            Reflect.deleteProperty(config, 'params');
        }
        return new Promise((resolve) => {
            request(config)
                .then((response: any) => {
                    const res = handleResponse(
                        response,
                        hideError,
                        returnAllResponse,
                        isShowResponseMessage
                    ) as unknown as T;
                    resolve(res);
                })
                .catch((response: any) => {
                    const res = handleResponse(
                        response,
                        hideError,
                        returnAllResponse,
                        isShowResponseMessage
                    ) as unknown as T;
                    resolve(res);
                })
                .finally(() => {
                    // todo
                    // 比如loading
                });
        });
    },
    /**
     * POST 请求
     * @template T
     * @param {string} url - 请求地址
     * @param {(Record<string | number,unknown | any>)} [params={}] - 请求参数
     * @param {IRequestOptions} [{
     *         hideError = false,
     *         returnAllResponse = false,
     *         isShowLoading = false,
     *         isShowResponseMessage = false,
     *         contentType = 'JSON'
     *         requestType = 'POST'
     *         responseType = 'json'
     *     }={}]
     * @return {*}  {Promise<T>}
     */
    httpPost<T = IResponse>(
        url: string,
        params: Record<string | number, unknown | any> = {},
        {
            hideError = false,
            returnAllResponse = false,
            isShowLoading = false,
            isShowResponseMessage = false,
            contentType = 'JSON',
            requestType = 'POST',
            responseType = 'json',
        }: IRequestOptions = {}
    ): Promise<T> {
        const configObj = rebuildPostData(params, contentType);
        const method: Method = requestType;
        const headers: any = {
            'content-type': configObj.headersConfig,
        };
        const { loadingInstance } = useLoading(isShowLoading);
        const config: AxiosRequestConfig = {
            url,
            method,
            data: configObj.params,
            // headers: useRequestHeaders(headers,isNoNeedToken),
            headers,
            responseType,
        };
        return new Promise((resolve) => {
            request(config)
                .then((response: any) => {
                    const res = handleResponse(
                        response,
                        hideError,
                        returnAllResponse,
                        isShowResponseMessage
                    ) as unknown as T;
                    resolve(res);
                })
                .catch((response: any) => {
                    const res = handleResponse(
                        response,
                        hideError,
                        returnAllResponse,
                        isShowResponseMessage
                    ) as unknown as T;
                    resolve(res);
                })
                .finally(() => {
                    // todo
                    // 比如loading
                });
        });
    },
};
